home *** CD-ROM | disk | FTP | other *** search
- /* */
- /***** kali.c - Nina Amenta, Aug. 1989 ******/
- /* */
- #include <stdio.h>
- #include <math.h>
- #include <gl.h>
- #include <device.h>
- #include "symmetry.h"
- #include "forms.h"
-
- LINE *ThrowAwayLines();
- void ClosestEndpoint();
- WINDOW MakeButtonWindow();
- LINE *NewLine();
- LINE *DropLine();
- LINE *GrabLine();
- LINE *MakeCurrentObject();
- LINE *ReadPattern();
- void DrawLine();
- void PickLine();
- char *KeyboardIO();
- void ChangeRatio();
- void ChangeScale();
- void ChangeAngle();
- void ChangeRotation();
- void SaveProc(FILE *pat);
- void LoadProc(FILE *pat);
- float distance();
-
- float zoom;
- RECTANGLE win_rect,sym_rect;
- int mode;
- POINT *sym_pts=NULL;
- int count;
- XFORM xforms[5];
- SYMMETRY *sym;
- int sym_index;
- LINE *Lines=NULL;
- WINDOW win;
- int pick_for;
- void (*xformfnc) ();
- int lit;
-
- #define QDEVICE fl_qdevice
- #define QTEST fl_qtest
- #define QREAD fl_qread
-
- extern void forms_init();
-
- #define NAMESTACKSIZE 50
-
- main()
- {
- EVENT ev;
- int i,j;
- int ref;
- FILE *pat;
- LINE *cur;
- POINT tmp;
- short dev_data;
- short namestack[NAMESTACKSIZE];
- short scaled_pick;
- int hits;
- char *filename;
- float dummy;
- int old;
-
- zoom = 1.0;
- mode = 0;
- sym_index = P6M;
- mode = 0;
-
- foreground();
-
- win = MakeWindow(&win_rect);
- SetUpOperatorInterface();
- sym = &(SYMTAB[sym_index]);
- DefineSymWindow(&sym_rect,sym,&win_rect,zoom);
- /* ortho2(0.0,zoom*win_rect.width,0.0,zoom*win_rect.height); */
- count = SetUpSymmetry(sym,&sym_pts,xforms,&sym_rect);
- DrawCurrent(&sym_rect,Lines,sym,sym_pts,xforms,count,DrawLine);
- swapbuffers();
-
- forms_init();
- fl_do_forms();
-
- for (;;) {
- if ((mode != DRAW) && (mode != TRANSFORM) && (mode != MOVE))
- ev = QREAD(&dev_data);
-
- /* mouse handler */
- else {
- while (((mode == DRAW) || (mode == MOVE)) &&
- ((ev=QTEST()==0) || (ev == INPUTCHANGE)))
- {
- GetCursor(&tmp,&win_rect,zoom);
- if (RectIncludesPoint(sym_rect,tmp))
- {
- tmp.x -= sym_pts[ref].x;
- tmp.y -= sym_pts[ref].y;
- VectorMatrixMult(&tmp,xforms[4],&tmp);
- Lines->m[EX]=tmp.x;
- Lines->m[EY]=tmp.y;
- DrawCurrent(&sym_rect,Lines,sym,
- sym_pts,xforms,count,DrawLine);
- swapbuffers();
- }
- }
- while ((mode == TRANSFORM) && (getbutton(LEFTMOUSE)) &&
- (((ev=QTEST())==0) || (ev == INPUTCHANGE)))
- {
- int new;
- new = getvaluator(MOUSEX);
- if (new>(old+1)) xformfnc(1,sym,&zoom);
- else if (new<(old-1)) xformfnc(-1,sym,&zoom);
- old = new;
- DefineSymWindow(&sym_rect,sym,&win_rect,zoom);
- /* ortho2(0.0,zoom*win_rect.width,0.0,zoom*win_rect.height); */
- count = SetUpSymmetry(sym,&sym_pts,xforms,&sym_rect);
- DrawCurrent(&sym_rect,Lines,sym,sym_pts,xforms,count,DrawLine);
- swapbuffers();
- }
-
- ev = QREAD(&dev_data);
- }
-
- if (ev==REDRAW)
- {
- reshapeviewport();
- AdjustWindowRectangle(&win_rect);
- DefineSymWindow(&sym_rect,sym,&win_rect,zoom);
- count = SetUpSymmetry(sym,&sym_pts,xforms,&sym_rect);
- DrawCurrent(&sym_rect,Lines,sym,sym_pts,xforms,count,DrawLine);
- swapbuffers();
- }
-
-
- /* button handlers */
-
- if (ev==LEFTMOUSE)
- {
- if (!dev_data) continue; /* do nothing on button release */
- if (mode == TRANSFORM)
- {
- old = getvaluator(MOUSEX);
- continue;
- }
- else if ((mode == PICK) && (pick_for == MOVE) && (lit == TRUE))
- {
- DrawCurrent(&sym_rect,Lines,sym,
- sym_pts,xforms,count,DrawLine);
- swapbuffers();
- mode = MOVE;
- lit = FALSE;
- continue;
- }
-
- /* lay down point */
- GetCursor(&tmp,&win_rect,zoom);
-
- /* if ((mode == 0) || (mode == DRAW) || (mode == MOVE)) */
- {
- if ((mode == DRAW) || (mode == MOVE)) /* fix endpoint */
- {
- POINT p;
- /* Reference to closest center of symmetry */
- p.x = tmp.x-sym_pts[ref].x;
- p.y = tmp.y-sym_pts[ref].y;
- /* Convert to standard basis */
- VectorMatrixMult(&p,xforms[4],&p);
- Lines->m[EX]=p.x;
- Lines->m[EY]=p.y;
- }
- if (mode == MOVE) mode = PICK;
- if (mode == 0) mode = DRAW;
- if (mode == DRAW) /* start drawing new line */
- {
- DrawCurrent(&sym_rect,Lines,sym,
- sym_pts,xforms,count,DrawLine);
- swapbuffers();
- ref = closest(&tmp,sym_pts,count);
- Lines = NewLine(Lines);
- NewId(Lines);
- /* Reference to closest center of symmetry */
- tmp.x -= sym_pts[ref].x;
- tmp.y -= sym_pts[ref].y;
- /* Convert to standard basis */
- VectorMatrixMult(&tmp,xforms[4],&tmp);
- Lines->m[EX]=Lines->m[SX]=tmp.x;
- Lines->m[EY]=Lines->m[SY]=tmp.y;
- }
- }
- }
-
-
- else if (ev==MIDDLEMOUSE) /* drop line */
- {
- if (!dev_data) continue; /* do nothing on button release */
- if ((Lines != NULL) &&
- ((mode == DRAW)
- || ((mode == PICK) && (lit == TRUE) && (pick_for == CUT)) ))
- {
- Lines = DropLine(Lines);
- DrawCurrent(&sym_rect,Lines,sym,
- sym_pts,xforms,count,DrawLine);
- swapbuffers();
- mode = (mode == DRAW) ? 0 : PICK;
- lit = FALSE;
- }
- }
-
- else if (ev == RIGHTMOUSE) /* pick */
- {
- if (!dev_data) continue; /* do nothing on button release */
- if (mode != PICK) continue;
-
- scaled_pick = zoom*10+1;
- picksize(scaled_pick,scaled_pick);
- pick(namestack,NAMESTACKSIZE);
- ortho2(0.0,zoom*win_rect.width,0.0,
- zoom*win_rect.height);
- initnames();
- pushname(-1); /* placeholders for first line */
- pushname(-1);
- pushname(-1);
- DrawCurrent(&sym_rect,Lines,sym,
- sym_pts,xforms,count,PickLine);
- hits = endpick(namestack);
- ortho2(0.0,zoom*win_rect.width,0.0,
- zoom*win_rect.height);
- DrawCurrent(&sym_rect,Lines,sym,
- sym_pts,xforms,count,DrawLine);
-
- if (hits > 0)
- {
- i = 0;
- while (namestack[4*i+1] == -1) i++;
- if (i >= hits) continue;
- Lines = GrabLine(namestack[4*i+2],Lines);
- if (pick_for == MOVE)
- {
- /* get correct rot & ref */
- UseRightCopy(Lines,sym,xforms,namestack[4*i+3]);
- ref = namestack[4*i+1]; /* correct translation */
- /* get cursor relative to ref */
- GetCursor(&tmp,&win_rect,zoom);
- tmp.x -= sym_pts[ref].x;
- tmp.y -= sym_pts[ref].y;
- /* Convert to standard basis */
- VectorMatrixMult(&tmp,xforms[4],&tmp);
- ClosestEndpoint(Lines,&tmp);
- HighLiteLine(&sym_rect,Lines,sym,
- sym_pts,xforms,count,MAGENTA);
- }
- else /* for delete - just lite up */
- {
- HighLiteLine(&sym_rect,Lines,sym,
- sym_pts,xforms,count,GREEN);
- }
- lit = TRUE;
- }
- else lit = FALSE;
- swapbuffers();
- }
- fl_do_forms();
- }
- }
-
-
- void ChangeScale(direction,sym,zoom)
- int direction;
- SYMMETRY *sym;
- float *zoom;
- {
- if (direction == 1) *zoom *= 0.95;
- else *zoom *= 1.05;
- }
-
- void ChangeRotation(direction,sym,zoom)
- int direction;
- SYMMETRY *sym;
- float *zoom;
- {
- double angle;
- XFORM rotation;
-
- if (direction == 1) angle = M_PI / 180;
- else angle = - M_PI / 180;
- SetUpRot(angle,rotation);
- VectorMatrixMult(&(sym->v1),rotation,&(sym->v1));
- VectorMatrixMult(&(sym->v2),rotation,&(sym->v2));
- }
-
- void ChangeRatio(direction,sym,zoom)
- int direction;
- SYMMETRY *sym;
- float *zoom;
- {
- if (direction == 1) VectorScalarMult(&sym->v1,1.1);
- else VectorScalarMult(&sym->v1,0.95);
- }
-
- void ChangeAngle(direction,sym,zoom)
- int direction;
- SYMMETRY *sym;
- float *zoom;
- {
- double angle;
- XFORM rotation;
-
- if (direction == 1) angle = M_PI / 360;
- else angle = - M_PI / 360;
- SetUpRot(angle,rotation);
- VectorMatrixMult(&(sym->v1),rotation,&(sym->v1));
- /* modify rotation matrix for opposite angle */
- rotation[1] = -rotation[1];
- rotation[2] = -rotation[2];
- VectorMatrixMult(&(sym->v2),rotation,&(sym->v2));
- }
-
-
- /* Move the selected line to first in the list */
- LINE *GrabLine(i,first)
- short i;
- LINE *first;
- {
- LINE *cur,*last;
-
- last = NULL; /* previous line we looked at, NOT last in the list */
- for (cur=first; cur != NULL; cur=cur->next)
- {
- if (cur->id == i)
- {
- if (last != NULL)
- {
- last->next = cur->next;
- cur->next = first;
- }
- first = cur;
- break;
- }
- last = cur;
- }
- return(first);
- }
-
-
- LINE *DropLine(L)
- LINE *L;
- {
- LINE *cur;
- cur = L->next;
- free(L);
- return(cur);
- }
-
-
- SetUpOperatorInterface()
- {
- QDEVICE(LEFTMOUSE);
- QDEVICE(MIDDLEMOUSE);
- QDEVICE(RIGHTMOUSE);
- }
-
-
- GetCursor(p,r,zoom)
- POINT *p;
- RECTANGLE *r;
- float zoom;
- {
- p->x = (getvaluator(MOUSEX)-r->x)*zoom;
- p->y = (getvaluator(MOUSEY)-r->y)*zoom;
- }
-
-
-
- DrawCurrent(rect,Lines,sym,pts,xforms,count,drawing_routine)
- RECTANGLE *rect;
- LINE *Lines;
- SYMMETRY *sym;
- POINT *pts;
- XFORM *xforms;
- int count;
- void (*drawing_routine) ();
- {
- LINE *obj;
- RECTANGLE bounds;
-
- winset(win);
- obj = MakeCurrentObject(Lines,sym,xforms,&bounds);
- color(WHITE);
- clear();
- color(BLACK);
- DrawPoints(pts,count);
- color(BLUE);
- ReplicateObject
- (rect,obj,pts,count,&bounds,&(sym->v1),&(sym->v2),drawing_routine);
- FreeObject(obj);
- }
-
- HighLiteLine(rect,cur,sym,pts,xforms,count,colour)
- RECTANGLE *rect;
- LINE *cur;
- SYMMETRY *sym;
- POINT *pts;
- XFORM *xforms;
- int count;
- Colorindex colour; /* note attractive British spelling */
- {
- LINE *obj,*temp;
- RECTANGLE bounds;
-
- winset(win);
- temp = cur->next;
- cur->next = NULL;
- obj = MakeCurrentObject(cur,sym,xforms,&bounds);
- cur->next = temp;
- color(colour);
- ReplicateObject
- (rect,obj,pts,count,&bounds,&(sym->v1),&(sym->v2),DrawLine);
- FreeObject(obj);
- }
-
-
-
- /* UseRightCopy - changes the endpoints of the line cur according
- to the pos'th transformation that goes into making an object.
- Since all transformations of a given line are eqivalent, this makes
- no difference in the picture */
-
- UseRightCopy(cur,sym,xforms,pos)
- LINE *cur;
- SYMMETRY *sym;
- XFORM *xforms;
- short pos;
- {
- RECTANGLE bounds;
- LINE *temp,*l,*obj;
-
- temp = cur->next;
- cur->next = NULL;
- obj = MakeCurrentObject(cur,sym,xforms,&bounds);
- for (l = obj; l->next != NULL; l = l->next) {
- if (l->obj_pos == pos) break;
- }
- *cur = *l; /* copy line description */
- FreeObject(obj);
- MatrixMultiply(cur->m,xforms[4],cur->m);
- cur->next = temp;
- }
-
-
- WINDOW MakeWindow(r)
- RECTANGLE *r;
- {
- WINDOW rwin;
-
- prefposition(233, 839, 8, 622);
- rwin = winopen("kali");
- minsize(32,32);
- maxsize(1024, 1280);
- winconstraints();
- AdjustWindowRectangle(r);
- doublebuffer();
- gconfig();
- return(rwin);
- }
-
- AdjustWindowRectangle(r)
- RECTANGLE *r;
- {
- long x,y;
-
- getorigin(&x,&y);
- r->x = x; r->y = y;
- getsize(&x,&y);
- r->width = x;
- r->height = y;
- }
-
-
-
- /* Find closest center of symmetry to new motif point */
- int closest(new_pt,pts,maxpts)
- POINT *new_pt;
- POINT *pts;
- int maxpts;
- {
- int i,min_i;
- float dist,min=HUGE;
-
- for (i=0; i<maxpts; i++)
- {
- dist = distance(new_pt->x, new_pt->y, pts[i].x, pts[i].y);
- if (dist < min) { min = dist; min_i = i; }
- }
- return(min_i);
- }
-
- PrintLine(l)
- LINE* l;
- {
- int i;
- printf("%x ",l);
- for (i=0;i<4;i++) printf("%6.3f ",l->m[i]);
- printf("%d %x \n",l->id,l->next);
- }
-
- DumpLines(Lines)
- LINE* Lines;
- {
- LINE* cur;
- int i;
- i = 0;
- for (cur=Lines; cur != NULL; cur=cur->next)
- {
- printf("Line %d ",i++);
- PrintLine(cur);
- }
- }
-
- complain(win_rect,zoom)
- RECTANGLE *win_rect;
- float zoom;
- {
- KeyboardIO(0,20.0,win_rect->height-20.0,
- "Bogus file name!",zoom);
- sleep(3);
- }
-
-
- LINE* ThrowAwayLines(Lines)
- LINE *Lines;
- {
- LINE *cur;
- for (cur=Lines; cur!=NULL; cur=cur->next)
- free(cur);
- return(NULL);
- }
-
-
- void SaveProc(FILE *pat)
- {
- LINE *cur;
-
- fprintf(pat,"%d\n",sym_index);
- fprintf(pat,"%6.3f %6.3f\n",
- sym_rect.width,sym_rect.height);
- fprintf(pat,"%6.3f %6.3f\n",
- sym->v1.x,sym->v1.y);
- fprintf(pat,"%6.3f %6.3f\n",
- sym->v2.x,sym->v2.y);
- fprintf(pat,"%6.3f \n",
- zoom);
- for (cur=Lines; cur != NULL; cur=cur->next)
- fprintf(pat,"%6.3f %6.3f %6.3f %6.3f\n",
- cur->m[0],cur->m[1],cur->m[2],cur->m[3]);
- fclose(pat);
- }
-
- void LoadProc(FILE *pat)
- {
- float dummy;
- fscanf(pat,"%d\n",&sym_index);
- fscanf(pat,"%f %f\n",&dummy,&dummy);
- sym = &(SYMTAB[sym_index]);
- fscanf(pat,"%f %f\n",
- &(sym->v1.x),&(sym->v1.y));
- fscanf(pat,"%f %f\n",
- &(sym->v2.x),&(sym->v2.y));
- fscanf(pat,"%f \n",
- &zoom);
- DefineSymWindow(&sym_rect,sym,&win_rect,zoom);
- /* ortho2(0.0,zoom*win_rect.width,0.0,
- zoom*win_rect.height); */
- count = SetUpSymmetry(sym,&sym_pts,
- xforms,&sym_rect);
- Lines = ThrowAwayLines(Lines);
- Lines = ReadPattern(Lines,pat);
-
-
- DrawCurrent(&sym_rect,Lines,sym,
- sym_pts,xforms,count,DrawLine);
- swapbuffers();
- mode = 0;
- }
-
-